package org.genesilico.workflow2.graphs.tests;

import junit.framework.Assert;

import org.genesilico.workflow2.graphs.GraphNode;
import org.genesilico.workflow2.graphs.GraphUtilities;
import org.genesilico.workflow2.graphs.Node;
import org.genesilico.workflow2.graphs.GraphUtilities.GraphError;
import org.genesilico.workflow2.graphs.isomorphism.PermutationsGenerator;
import org.junit.Test;

public class AdvancedTests {
	/**
	 * Creates "a long graph" and randomly permutes it a number of times. Each
	 * permutation should be isomorphic with the graph.
	 */
	@Test
	public void longGraph() {
		final int SIZE = 1000;
		GraphNode[] g1 = new GraphNode[SIZE];
		for (int i = 0; i < g1.length; i++) {
			g1[i] = new GraphNode(i, new Node("sameNodesMeansHarder :P"),
					new int[] { i - 1 }, new int[] { i + 1 });
		}
		g1[0].parents = new int[] {};
		g1[SIZE - 1].children = new int[] {};

		for (int i = 0; i < 1000; i++) {
			GraphNode[] g2 = PermutationsGenerator.permuteGraphNodes(g1);
			Assert.assertTrue(GraphUtilities.assessIsomorphismBetweenGraphs(g1,
					g2));
			System.out.println(i);
		}
	}

	/**
	 * Creates "a dense graph" and randomly permutes it a number of times. Each
	 * permutation should be isomorphic with the graph.
	 */
	@Test
	public void bigGraph() {
		GraphNode[] g = new GraphNode[15];
		final Node n = new Node("content");
		g[0] = new GraphNode(0, n, new int[] {}, new int[] { 1, 3 });
		g[1] = new GraphNode(1, n, new int[] { 0 }, new int[] { 2, 4 });
		g[2] = new GraphNode(2, n, new int[] { 1 }, new int[] { 5, 6 });
		g[3] = new GraphNode(3, n, new int[] { 0 }, new int[] { 7, 8 });
		g[4] = new GraphNode(4, n, new int[] { 1 }, new int[] { 7, 8, 9 });
		g[5] = new GraphNode(5, n, new int[] { 2 }, new int[] { 8, 9, 10 });
		g[6] = new GraphNode(6, n, new int[] { 2 }, new int[] { 9, 10 });
		g[7] = new GraphNode(7, n, new int[] { 3, 4 }, new int[] { 11, 12 });
		g[8] = new GraphNode(8, n, new int[] { 3, 4, 5 }, new int[] { 12, 13 });
		g[9] = new GraphNode(9, n, new int[] { 4, 5, 6 }, new int[] { 13, 14 });
		g[10] = new GraphNode(10, n, new int[] { 5, 6 }, new int[] { 14 });
		g[11] = new GraphNode(11, n, new int[] { 7 }, new int[] {});
		g[12] = new GraphNode(12, n, new int[] { 7, 8 }, new int[] {});
		g[13] = new GraphNode(13, n, new int[] { 8, 9 }, new int[] {});
		g[14] = new GraphNode(14, n, new int[] { 9, 10 }, new int[] {});

		Assert.assertEquals(GraphUtilities.hasError(g, true, true, true),
				GraphError.Good);

		for (int i = 0; i < 1000; i++) {
			GraphNode[] g2 = PermutationsGenerator.permuteGraphNodes(g);
			boolean f = GraphUtilities.assessIsomorphismBetweenGraphs(g, g2);
			Assert.assertTrue(f);
			System.out.println(i);
		}
	}
	
	@Test
	public void test1() {
		final Node n = new Node("content");

		GraphNode[] g1 = new GraphNode[12];
		g1[0] = new GraphNode(0, n, new int[] {}, new int[] { 3, 4 });
		g1[1] = new GraphNode(1, n, new int[] {}, new int[] { 3, 5 });
		g1[2] = new GraphNode(2, n, new int[] {}, new int[] { 4, 5 });
		g1[3] = new GraphNode(3, n, new int[] { 0, 1 }, new int[] { 6, 7 });
		g1[4] = new GraphNode(4, n, new int[] { 0, 2 }, new int[] { 6, 8 });
		g1[5] = new GraphNode(5, n, new int[] { 1, 2 }, new int[] { 7, 8 });
		g1[6] = new GraphNode(6, n, new int[] { 3, 4 }, new int[] { 9, 10 });
		g1[7] = new GraphNode(7, n, new int[] { 3, 5 }, new int[] { 9, 11 });
		g1[8] = new GraphNode(8, n, new int[] { 4, 5 }, new int[] { 10, 11 });
		g1[9] = new GraphNode(9, n, new int[] { 6, 7 }, new int[] {});
		g1[10] = new GraphNode(10, n, new int[] { 6, 8 }, new int[] {});
		g1[11] = new GraphNode(11, n, new int[] { 7, 8 }, new int[] {});

		GraphNode[] g2 = new GraphNode[12];
		g2[0] = new GraphNode(0, n, new int[] {}, new int[] { 3, 4 });
		g2[1] = new GraphNode(1, n, new int[] {}, new int[] { 3, 5 });
		g2[2] = new GraphNode(2, n, new int[] {}, new int[] { 4, 5 });
		g2[3] = new GraphNode(3, n, new int[] { 0, 1 }, new int[] { 6, 8 });
		g2[4] = new GraphNode(4, n, new int[] { 0, 2 }, new int[] { 6, 7 });
		g2[5] = new GraphNode(5, n, new int[] { 1, 2 }, new int[] { 7, 8 });
		g2[6] = new GraphNode(6, n, new int[] { 3, 4 }, new int[] { 9, 10 });
		g2[7] = new GraphNode(7, n, new int[] { 4, 5 }, new int[] { 9, 11 });
		g2[8] = new GraphNode(8, n, new int[] { 3, 5 }, new int[] { 10, 11 });
		g2[9] = new GraphNode(9, n, new int[] { 6, 7 }, new int[] {});
		g2[10] = new GraphNode(10, n, new int[] { 6, 8 }, new int[] {});
		g2[11] = new GraphNode(11, n, new int[] { 7, 8 }, new int[] {});
		
		Assert.assertEquals(GraphUtilities.hasError(g1, true, true, true),
				GraphError.Good);

		Assert.assertEquals(GraphUtilities.hasError(g2, true, true, true),
				GraphError.Good);

		boolean f = GraphUtilities.assessIsomorphismBetweenGraphs(g1, g2);
		Assert.assertTrue(f);
	}
}
